package com.yj.auto.plugin.log4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.servlet.AsyncContext;

import com.jfinal.log.Log;

/**
 * log4j异步输出处理类
 *
 */
public class Log4jAsyncWriter extends Writer {

	private static final Log logger = Log.getLog(Log4jAsyncWriter.class);

	/**
	 * AsyncContext队列
	 */
	private static final Queue<AsyncContext> asyncContextQueue = new ConcurrentLinkedQueue<AsyncContext>();

	/**
	 * 添加AsyncContext对象到队列
	 * 
	 * @param ac
	 */
	public static void addAsyncContext(AsyncContext ac) {
		asyncContextQueue.add(ac);
	}

	/**
	 * 删除AsyncContext队列对象
	 * 
	 * @param ac
	 */
	public static void removeAsyncContext(AsyncContext ac) {
		if (null != ac) {
			asyncContextQueue.remove(ac);
			try {
				ac.getResponse().getWriter().flush();
			} catch (IOException e) {
			}
			try {
				ac.getResponse().getWriter().close();
			} catch (IOException e) {
			}
		}
	}

	public void sync(String msg) {
		for (AsyncContext ac : asyncContextQueue) {
			AsyncContext asyncContext = ac;
			try {
				PrintWriter writer = ac.getResponse().getWriter();
				writeJS(writer, msg);
			} catch (IOException e) {
				asyncContextQueue.remove(asyncContext);
				logger.error("Log4jAsyncWriter IOException 异常!", e);
			}
		}
	}

	public static void writeJS(PrintWriter writer, String s) {
		StringBuffer js = new StringBuffer("<script type=\"text/javascript\">");
		js.append("parent.addLog4jHtml(\"").append(s.replaceAll("\n", "").replaceAll("\r", "").replaceAll("\"", "'")).append("\");");
		js.append("</script>");
		writer.println(js.toString());
		writer.flush();
	}

	@Override
	public void write(char[] cbuf, int off, int len) throws IOException {
		if (asyncContextQueue.size() < 1)
			return;
		try {
			String msg = new String(cbuf, off, len);
			this.sync(msg);
		} catch (Exception e) {
			logger.error("log4j write error", e);
		}
	}

	@Override
	public void flush() throws IOException {
	}

	@Override
	public void close() throws IOException {

	}

}
